#include <string>
#include <iostream>
using namespace std;
struct Animal
{
    virtual std::string getName() const
    {
        return "animal";
    }
};
struct Cat : public Animal
{
    std::string getName() const
    {
        return "cat";
    }
    void meow() const
    {
        cout << "Meow!" << endl;
    }
};
struct Dog : public Animal
{
    std::string getName() const
    {
        return "dog";
    }
    void bark() const
    {
        cout << "Woof!" << endl;
    }
};
void tryBark(const Animal *a)
{
    // dynamic_cast 做了两件事：
    // 检查 a 所指向的“实际”类型是否为 Dog；
    // 若是，则得到 const Dog* 类型的值，指向这个 Dog；否则，得到 nullptr。
    const Dog *dog{dynamic_cast<const Dog *>(a)};
    if (dog != nullptr)
    { // 也可写作 if (dog) { ... }
        dog->bark();
    }
    else
    {
        cout << "Not a dog, cannot bark." << endl;
    }
}

int main()
{
    Animal *a1 = new Cat;
    Animal *a2 = new Dog;
    cout << a1->getName() << endl; // Outputs "cat"
    cout << a2->getName() << endl; // Outputs "dog"
    tryBark(a1);                   // Does nothing
    tryBark(a2);                   // Calls bark()
    delete a1;
    delete a2;
    return 0;
    // typeid 运算符和 dynamic_cast 是 C++ 中 RTTI 的体现方法。
    // 它们共同的特点是可以获取一个指针指向的运行时“实际”类型。而获取“实际”类型这个过程并不是容易实现的，它需要保存一些额外信息——多态信息。
    // 一般地，这些信息会与虚函数调用相关的一些内部结构相关，所以 C++ 只允许拥有虚函数的类使用 RTTI
}